import type { SweetAlertOptions } from 'sweetalert2'
import { mergeWith } from 'lodash'

/**
 * 类名合并策略类型
 */
export type ClassMergeStrategy
  = | 'concat' // 简单拼接 (a + b)
    | 'replace' // 完全替换 (b)
    | 'dedupe' // 去重合并 (a ∪ b)
    | ((existing: string, incoming: string) => string) // 自定义函数

/**
 * 类名合并配置
 */
export interface ToastClassMergeConfig {
  container?: ClassMergeStrategy
  popup?: ClassMergeStrategy
  confirmButton?: ClassMergeStrategy
  cancelButton?: ClassMergeStrategy
  // 可扩展其他属性...
  [key: string]: ClassMergeStrategy | undefined
}

/**
 * 深度合并处理器
 */
export class MergeHandler {
  private static instance: MergeHandler
  private readonly toastClassMergeConfig: ToastClassMergeConfig = {
    container: 'dedupe',
    popup: 'concat',
    confirmButton: 'replace',
    cancelButton: 'replace',
    __default: 'concat',
  }

  public static getInstance(): MergeHandler {
    if (!MergeHandler.instance) {
      MergeHandler.instance = new MergeHandler()
    }
    return MergeHandler.instance
  }

  /**
   * 通用对象深度合并
   * @param objects 要合并的对象数组（最后一个参数可以是自定义合并函数）
   */
  deepMerge<T extends object>(
    ...objects: [...Array<Partial<T>>, (objValue: any, srcValue: any, key: string) => any] | Array<Partial<T>>
  ): T {
    // 检查最后一个参数是否是函数
    const lastArg = objects[objects.length - 1]

    if (typeof lastArg === 'function') {
      const configs = objects.slice(0, -1) as Array<Partial<T>>
      const customizer = lastArg as (objValue: any, srcValue: any, key: string) => any
      return mergeWith({}, ...configs, customizer)
    }

    return mergeWith({}, ...objects as Array<Partial<T>>)
  }

  /**
   * SweetAlert 专用深度合并
   */
  deepMergeSweetAlert(...configs: SweetAlertOptions[]): SweetAlertOptions {
    return mergeWith({}, ...configs, this.createSweetAlertCustomizer())
  }

  /**
   * 创建自定义合并处理器
   */
  private createSweetAlertCustomizer(): (obj: any, src: any, key: string) => any {
    return (objValue, srcValue, key) => {
      // 处理 customClass 的深度合并
      if (key === 'customClass' && srcValue) {
        const result = { ...objValue }
        for (const classKey in srcValue) {
          if (srcValue[classKey] != null) {
            result[classKey] = this.mergeClassProperty(
              objValue?.[classKey],
              srcValue[classKey],
              classKey,
            )
          }
        }
        return Object.keys(result).length ? result : undefined
      }

      // 处理 didOpen 等函数合并
      if (key === 'didOpen' && typeof objValue === 'function') {
        return (...args: any[]) => {
          objValue(...args)
          srcValue(...args)
        }
      }

      return undefined // 其他字段走默认合并
    }
  }

  /**
   * 执行类名合并策略
   */
  private mergeClassProperty(
    existing: string | undefined,
    incoming: string,
    propertyName: string,
  ): string {
    const strategy = this.toastClassMergeConfig[propertyName]
      ?? this.toastClassMergeConfig.__default
      ?? 'concat'

    const existingClasses = existing || ''
    const incomingClasses = incoming || ''

    switch (strategy) {
      case 'concat':
        return `${existingClasses} ${incomingClasses}`.trim()
      case 'replace':
        return incomingClasses
      case 'dedupe':
        return this.dedupeClassNames(existingClasses, incomingClasses)
      default:
        return typeof strategy === 'function'
          ? strategy(existingClasses, incomingClasses)
          : existingClasses
    }
  }

  /**
   * 类名去重合并
   */
  private dedupeClassNames(existing: string, incoming: string): string {
    return [
      ...new Set(
        `${existing} ${incoming}`
          .trim()
          .split(/\s+/)
          .filter(cls => cls), // 过滤空字符串
      ),
    ].join(' ')
  }
}
